www.gusucode.com > VC++ 编写软件自动升级服务源代码 > VC++ 编写软件自动升级服务源代码/gusucode/updater_src0.8.1.6/CheckVersion.cpp
/******************************************************************** created: 2005/03/02 created: 2:3:2005 10:53 filename: CheckVersion.cpp file path: Updater file base: CheckVersion file ext: cpp author: Geert van Horrik purpose: *********************************************************************/ //********************************************************************* // INCLUDES //********************************************************************* #include "stdafx.h" #include "Updater.h" #include "CheckVersion.h" #include "ConnectionTest.h" // Test internet connection typedef LPTSTR (* UPDATESELECTORPROC)(); //********************************************************************* // MESSAGE MAP //********************************************************************* BEGIN_MESSAGE_MAP(CCheckVersion, CWinThread) ON_THREAD_MESSAGE(WMU_DOWNLOAD_COMPLETE, OnDownloadComplete) ON_THREAD_MESSAGE(WMU_ERROR, OnError) ON_THREAD_MESSAGE(WMU_SETPARENT, OnSetParent) ON_THREAD_MESSAGE(WMU_THREADMESSAGE, OnThreadMessage) END_MESSAGE_MAP() //********************************************************************* // CONSTRUCTOR & DESTRUCTOR //********************************************************************* IMPLEMENT_DYNCREATE(CCheckVersion, CWinThread) //===================================================================== CCheckVersion::CCheckVersion() { } //===================================================================== CCheckVersion::~CCheckVersion() { } //********************************************************************* // PUBLIC FUNCTIONS //********************************************************************* BOOL CCheckVersion::InitInstance() { // Set parent to NULL m_pParent = NULL; // We are not started yet m_bStarted = false; m_bNoFailPossible = false; m_bUpdateSelector = false; // Init singleton classes m_pFunctions = CFunctions::Instance(); m_pSettings = CSettings::Instance(); m_pUpdateInfo = CUpdateInfo::Instance(); m_pInternet = CInternet::Instance(); m_pSections = CSections::Instance(); m_pPath = CPath::Instance(); // Set parent for internet m_pInternet->SetParent(this); return TRUE; } //===================================================================== int CCheckVersion::ExitInstance() { // Always stop the downloads m_pInternet->StopDownloading(); // Auto clean-up thread m_bAutoDelete = TRUE; // Call original function return CWinThread::ExitInstance(); } //********************************************************************* // PRIVATE FUNCTIONS //********************************************************************* void CCheckVersion::Main() { // We are not ready yet m_bDownloadsReady = false; // Should we check if we are connected? if (m_pSettings->GetCheckConnection()) { // Check if we are connected to the internet if (!CConnectionTest::Connected()) { // Send error message PostMessageToParent(WMU_ERROR, ERROR_NOCONNECTION, 0); PostThreadMessage(WM_QUIT, 0, 0); return; } } // Should we use update file or update selector? if (m_pSettings->GetUpdateSelector().IsEmpty()) { // No update selector m_bUpdateSelector = false; // Start downloading of update list if (!m_pInternet->DownloadFile(m_pSettings->GetURL(), m_pPath->GetPathUpdaterTemp() + "updatefile.xml")) { // Post error PostMessageToParent(WMU_ERROR, ERROR_SERVER, 0); } } else { // Update selector m_bUpdateSelector = true; // Start downloading of update list if (!m_pInternet->DownloadFile(m_pSettings->GetUpdateSelector(), m_pPath->GetPathUpdaterTemp() + "updateselector.dll")) { // Post error PostMessageToParent(WMU_ERROR, ERROR_SERVER, 0); } } } //===================================================================== bool CCheckVersion::CheckSections() { // Search for at least 1 section that needs to be updated for (int i = 0; i < m_pUpdateInfo->GetSectionCount(); i++) { // Check version if (m_pFunctions->CompareVersions(m_pUpdateInfo->GetSectionData(i)->GetVersion(), m_pSections->GetSectionVersion(m_pUpdateInfo->GetSectionData(i)->GetName())) == COMPAREVERSION_FIRSTLARGER) return true; } // If we get here, no new version is available return false; } //===================================================================== bool CCheckVersion::CheckVersionSeparately() { // Declare variables bool bUpdate = false, bUpdateFile; bool bFileProcessed; CString sFiledate = ""; // For all files, check difference for (int i = 0; i < m_pUpdateInfo->GetFileCount(); i++) { // Default, don't update the file m_pUpdateInfo->GetFileData(i)->SetUpdateFile(false); // We haven't processed the file bFileProcessed = false; bUpdateFile = false; // Check by version if (m_pUpdateInfo->GetFileData(i)->GetCheckType() == CHECK_VERSION) { // We processed the file bFileProcessed = true; // Check if there is a new version available if (m_pFunctions->CompareVersions(m_pUpdateInfo->GetFileData(i)->GetVersion(), m_pFunctions->GetFileVersion(m_pUpdateInfo->GetFileData(i)->GetFilename())) == COMPAREVERSION_FIRSTLARGER) { // There is a new version bUpdateFile = true; } } // Check by date if (m_pUpdateInfo->GetFileData(i)->GetCheckType() == CHECK_DATE) { // We processed the file bFileProcessed = true; // If empty, check automatically if (m_pUpdateInfo->GetFileData(i)->GetDate().IsEmpty()) { // Get filedate sFiledate = GetInternetFileDate(i, false); } else { // Get filedate sFiledate = m_pUpdateInfo->GetFileData(i)->GetDate(); } // Compare the date if (sFiledate > m_pFunctions->GetFileDate(m_pUpdateInfo->GetFileData(i)->GetFilename())) { // Different version bUpdateFile = true; } } // Check by date/time if (m_pUpdateInfo->GetFileData(i)->GetCheckType() == CHECK_DATETIME) { // We processed the file bFileProcessed = true; // If empty, check automatically if (m_pUpdateInfo->GetFileData(i)->GetDate().IsEmpty()) { // Get filedate sFiledate = GetInternetFileDate(i, true); } else { // Get filedate sFiledate = m_pUpdateInfo->GetFileData(i)->GetDate(); } // Compare the date if (sFiledate > m_pFunctions->GetFileDateTime(m_pUpdateInfo->GetFileData(i)->GetFilename())) { // Different version bUpdateFile = true; } } // Check by hash if (m_pUpdateInfo->GetFileData(i)->GetCheckType() == CHECK_HASH) { // We processed the file bFileProcessed = true; // Compare the hashes if (m_pUpdateInfo->GetFileData(i)->GetHash() != m_pFunctions->GetFileMD5Hash(m_pUpdateInfo->GetFileData(i)->GetFilename())) { // Different hash bUpdateFile = true; } } // If we didn't process the file, it should ALWAYS be updated if (!bFileProcessed) { bUpdateFile = true; } // Store information if we should update the file or not m_pUpdateInfo->GetFileData(i)->SetUpdateFile(bUpdateFile); if (bUpdateFile) { // We have at least one file to update bUpdate = true; } } // Return the result return bUpdate; } //===================================================================== CString CCheckVersion::GetInternetFileDate(int iFileIndex, bool bTimeToo) { // Declare variables CString sDate = "1970-01-01"; // For all download locations, check for (int j = 0; j < m_pUpdateInfo->GetFileData(iFileIndex)->GetActionCount(); j++) { // Get action CActionBase * pAction = m_pUpdateInfo->GetFileData(iFileIndex)->GetAction(j); // Are we dealing with download action? if (pAction->GetType() == ACTION_DOWNLOAD) { // Get download action CActionDownload * pDownload = (CActionDownload *)pAction; // Init k int k = 0; // Loop all locations while (k < pDownload->GetDownloadLocationCount() && ((sDate == "1970-01-01") || (sDate == "1970-01-01/00:00:00"))) { // Check what we should get if (bTimeToo) { sDate = m_pInternet->GetFileDateTime(pDownload->GetDownloadLocation(k)); } else { sDate = m_pInternet->GetFileDate(pDownload->GetDownloadLocation(k)); } } } } // Return value return sDate; } //===================================================================== void CCheckVersion::PostMessageToParent(UINT message, WPARAM wParam, LPARAM lParam) { // Check if parent is still valid if (!IsBadReadPtr(m_pParent, sizeof(CWinThread *))) { // Send message m_pParent->PostThreadMessage(message, wParam, lParam); } } //===================================================================== void CCheckVersion::OnDownloadComplete(WPARAM wParam, LPARAM lParam) { // Declare variables CString sUpdateLocation; HMODULE hModule; UPDATESELECTORPROC SelectUpdate; // Did we download update selector? if (m_bUpdateSelector) { // Don't handle this code again m_bUpdateSelector = false; // Load dll hModule = LoadLibrary(m_pPath->GetPathUpdaterTemp() + "\\updateselector.dll"); // Check if dll is loaded successfully if (hModule) { // Get proc address SelectUpdate = (UPDATESELECTORPROC) GetProcAddress(hModule, "SelectUpdate"); // Execute function in dll if (SelectUpdate != NULL) { sUpdateLocation = SelectUpdate(); } // Release dll FreeLibrary(hModule); } // Delete dll again DeleteFile(m_pPath->GetPathUpdaterTemp() + "\\updateselector.dll"); // Start downloading of update list if (!m_pInternet->DownloadFile(sUpdateLocation, m_pPath->GetPathUpdaterTemp() + "updatefile.xml")) { // Post error PostMessageToParent(WMU_ERROR, ERROR_SERVER, 0); } return; } // Are we ready downloading yet? if (!m_bDownloadsReady) { // Check if this is the right update file (sequenced updating) sUpdateLocation = m_pUpdateInfo->GetPreviousUpdate(m_pPath->GetPathUpdaterTemp() + "updatefile.xml"); if (!sUpdateLocation.IsEmpty()) { // Download next one if (!m_pInternet->DownloadFile(sUpdateLocation, m_pPath->GetPathUpdaterTemp() + "updatefile.xml")) { // Post error PostMessageToParent(WMU_ERROR, ERROR_SERVER, 0); } return; } else { // Read update list if (!m_pUpdateInfo->ReadFile(m_pPath->GetPathUpdaterTemp() + "updatefile.xml")) { // Send error message PostMessageToParent(WMU_ERROR, ERROR_FILECORRUPT, (LPARAM)_T("updatefile.xml")); PostThreadMessage(WM_QUIT, 0, 0); return; } // We should delete the file for security reasons DeleteFile(m_pPath->GetPathUpdaterTemp() + "updatefile.xml"); // Should we download other file? if (m_pUpdateInfo->GetSelfUpdate()) { // Should we download custom or default update script? if (m_pSettings->GetSelfUpdateLocation().IsEmpty()) { // Use default if (!m_pInternet->DownloadFile(UPDATER_UPDATELOCATION, m_pPath->GetPathUpdaterTemp() + "selfupdate.xml")) { // Just fake we are ready PostThreadMessage(WMU_DOWNLOAD_COMPLETE, 0, 0); } } else { // Use custom if (!m_pInternet->DownloadFile(m_pSettings->GetSelfUpdateLocation(), m_pPath->GetPathUpdaterTemp() + "selfupdate.xml")) { // Just fake we are ready PostThreadMessage(WMU_DOWNLOAD_COMPLETE, 0, 0); } } // Now we are ready downloading & updater cannot fail m_bDownloadsReady = true; m_bNoFailPossible = true; return; } } } // Read self update info if (PathFileExists(m_pPath->GetPathUpdaterTemp() + "selfupdate.xml")) { m_pUpdateInfo->ReadSelfUpdateFile(m_pPath->GetPathUpdaterTemp() + "selfupdate.xml"); } // Should we check all files separately? if (m_pUpdateInfo->GetCheckSeparately()) { // Check for all files, returns true if at least one file should be updated if (!CheckVersionSeparately()) { // Send error message PostMessageToParent(WMU_ERROR, ERROR_NONEWVERSION, 0); PostThreadMessage(WM_QUIT, 0, 0); return; } } else { // First check for sections if (!CheckSections()) { // Check if there is a new version available for the product if (m_pFunctions->CompareVersions(m_pUpdateInfo->GetNewVersion(), m_pSettings->GetAppVersion()) != COMPAREVERSION_FIRSTLARGER) { // Send error message PostMessageToParent(WMU_ERROR, ERROR_NONEWVERSION, 0); PostThreadMessage(WM_QUIT, 0, 0); return; } } } // Send message to parent that we are ready PostMessageToParent(WMU_TASK_COMPLETE, TASK_CHECKVERSION, 0); // Exit the thread PostThreadMessage(WM_QUIT, 0, 0); } //===================================================================== void CCheckVersion::OnError(WPARAM wParam, LPARAM lParam) { // The download failed! if (m_bNoFailPossible) { // Updater can't fail, so just ignore it PostThreadMessage(WMU_DOWNLOAD_COMPLETE, 0, 0); } else { // Report error PostMessageToParent(WMU_ERROR, ERROR_SERVER, (LPARAM)"updatefile.xml"); // Exit thread PostThreadMessage(WM_QUIT, 0, 0); } } //===================================================================== void CCheckVersion::OnSetParent(WPARAM wParam, LPARAM lParam) { // Set parent m_pParent = (CWinThread *)wParam; } //===================================================================== void CCheckVersion::OnThreadMessage(WPARAM wParam, LPARAM lParam) { // Declare variables int iThreadAction = (int)wParam; // Check what task to perform for thread switch (iThreadAction) { case THREAD_START: // Are we already started? if (!m_bStarted) { // Start main functions Main(); } break; case THREAD_PAUSE: // Pause thread SuspendThread(); break; case THREAD_RESUME: // Resume thread ResumeThread(); break; case THREAD_CANCEL: // Exit thread PostThreadMessage(WM_QUIT, 0, 0); break; case THREAD_FINISH: // Exit thread PostThreadMessage(WM_QUIT, 0, 0); break; } }